package ru.uskov.trainer;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ru.uskov.trainer.datastore.IUser;
import ru.uskov.trainer.datastore.impl.ContextGenerator;
import ru.uskov.trainer.model.IProductItem;
import ru.uskov.trainer.model.UserAuthData;
import ru.uskov.trainer.model.WrongArgumentException;

public class Ajax extends HttpServlet {

  private static final long serialVersionUID = 1L;

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    System.out.println("Ajax: doGet");
    response.setCharacterEncoding("utf-8");
    response.setContentType("text/html");
    UserAuthData uad = Utils.getUserId(request.getCookies());
    IUser user = null;
    if (uad.userIdIsCorrect()) {
      user = ContextGenerator.getInstance().getUserData(uad);
    }
    if (returnProducts(request, response)) {
      return;
    }
    if (returnWeight(request, response)) {
      return;
    }
    if (addProduct(request, response,user)) {
      return;
    }
    if (deleteOneItem(request, response,user)) {
      return;
    }
    if (deleteAllItems(request, response,uad, user)) {
      return;
    }

    ServletOutputStream sos = response.getOutputStream();
    sos.println("Response " + request.getParameter("id"));
    sos.close();
  }

  private void generateProductTable(HttpServletRequest request, HttpServletResponse response, String errorMessage, IUser user) throws IOException, ServletException {
    Reader reader = new InputStreamReader(Utils.class.getResourceAsStream("/productTable.vm"), MainPage.CODEPAGE);
    try {
      Map<String, Object> arguments = new HashMap<String, Object>();
      arguments.put("context", ContextGenerator.getInstance());
      List<IProductItem> selectedItems = new ArrayList<IProductItem>();
      if (user != null) {
        selectedItems = user.getProducts();
      }
      arguments.put("summ", ContextGenerator.getInstance().getSum(selectedItems));
      arguments.put("selectedProducts", selectedItems);
      if (errorMessage != null) {
        arguments.put("errorMessage", errorMessage);
      }
      String result = Utils.compileTemplate(reader, arguments);
      response.getWriter().append(result);
    } finally {
      reader.close();
    }
  }

  private boolean deleteAllItems(HttpServletRequest request, HttpServletResponse response, UserAuthData uad, IUser user) throws IOException, ServletException {
    if ("deleteAll".equals(request.getParameter("Subject"))) {
      String message = null;
      try {
        ContextGenerator.getInstance().removeAllProducts(uad);
      } catch (WrongArgumentException e) {
        message = e.getUserMessage();
      }
      generateProductTable(request, response, message, user);
      return true;
    }
    return false;
  }
  private boolean deleteOneItem(HttpServletRequest request, HttpServletResponse response, IUser user) throws IOException, ServletException {
    if ("deleteOneItem".equals(request.getParameter("Subject"))) {
      String itemId = request.getParameter("itemNumber");
      String message = null;
      try {
        ContextGenerator.getInstance().removeProduct(user, itemId);
      } catch (WrongArgumentException e) {
        message = e.getUserMessage();
      }
      generateProductTable(request, response, message, user);
      return true;
    }
    return false;
  }

  private boolean addProduct(HttpServletRequest request, HttpServletResponse response, IUser user) throws IOException, ServletException {
    if ("addProductItem".equals(request.getParameter("Subject"))) {
      String groupId = request.getParameter("productGroup");
      String productId = request.getParameter("productId");
      String quantity = request.getParameter("quantity");
      if (quantity != null) {
        quantity = quantity.replace(',', '.');
      }
      String units = request.getParameter("units");
      String message = null;
      try {
        ContextGenerator.getInstance().addProduct(user, groupId, productId, quantity, units);
      } catch (WrongArgumentException e) {
        message = e.getUserMessage();
      }
      generateProductTable(request, response, message, user);
      return true;
    }
    return false;
  }

  private boolean returnProducts(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    if ("selectProductGroup".equals(request.getParameter("Subject"))) {
      Reader reader = new InputStreamReader(Utils.class.getResourceAsStream("/productDiv.vm"));
      try {
        Map<String, Object> arguments = new HashMap<String, Object>();
        arguments.put("groupId", request.getParameter("groupId"));
        arguments.put("context", ContextGenerator.getInstance());
        String result = Utils.compileTemplate(reader, arguments);
        response.getWriter().append(result);
      } finally {
        reader.close();
      }
      return true;
    }
    return false;
  }

  private boolean returnWeight(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    if ("weightForm".equals(request.getParameter("Subject"))) {
      String weight = request.getParameter("weight");
      String wantedWeight = request.getParameter("wantedWeight");
      String height = request.getParameter("height");
      PrintWriter writer = response.getWriter();
      writer.append("w=" + weight + " " + wantedWeight + " " + height);
      return true;
    }
    return false;
  }

  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    doGet(request, response);
  }
}
